#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# @Date : 2024/4/10 10:37
# @Author : water
# @Description : 装饰器
"""
装饰器
    装饰器（decorators）是 Python 中的一种高级功能，它允许你动态地修改函数或类的行为。
    装饰器是一种函数，它接受一个函数作为参数，并返回一个新的函数或修改原来的函数。
    装饰器的语法使用 @decorator_name 来应用在函数或方法上。
    Python 还提供了一些内置的装饰器，比如 @staticmethod 和 @classmethod，用于定义静态方法和类方法。
    装饰器的应用场景：
        日志记录: 装饰器可用于记录函数的调用信息、参数和返回值。
        性能分析: 可以使用装饰器来测量函数的执行时间。
        权限控制: 装饰器可用于限制对某些函数的访问权限。
        缓存: 装饰器可用于实现函数结果的缓存，以提高性能。
    基本语法
    Python 装饰允许在不修改原有函数代码的基础上，动态地增加或修改函数的功能，装饰器本质上是一个接收函数作为输入并返回一个新的包装过后的函数的对象。
        def decorator_function(original_function):
            def wrapper(*args, **kwargs):
                # 这里是在调用原始函数前添加的新功能
                before_call_code()

                result = original_function(*args, **kwargs)

                # 这里是在调用原始函数后添加的新功能
                after_call_code()

                return result
            return wrapper

        # 使用装饰器
        @decorator_function
        def target_function(arg1, arg2):
            pass  # 原始函数的实现
    解析：decorator 是一个装饰器函数，它接受一个函数 func 作为参数，并返回一个内部函数 wrapper，在 wrapper 函数内部，你可以执行一些额外的操作，然后调用原始函数 func，并返回其结果。
        decorator_function 是装饰器，它接收一个函数 original_function 作为参数。
        wrapper 是内部函数，它是实际会被调用的新函数，它包裹了原始函数的调用，并在其前后增加了额外的行为。
        当我们使用 @decorator_function 前缀在 target_function 定义前，Python会自动将 target_function 作为参数传递给 decorator_function，然后将返回的 wrapper 函数替换掉原来的 target_function。

    使用装饰器
        装饰器通过 @ 符号应用在函数定义之前
    带参数的装饰器
        装饰器函数也可以接受参数
    类装饰器
        除了函数装饰器，Python 还支持类装饰器。类装饰器是包含 __call__ 方法的类，它接受一个函数作为参数，并返回一个新的函数
"""


# 装饰器（可以带参数，也可以不带参数）
def decorator_function(original_function):
    def wrapper(*args, **kwargs):
        # 这里是在调用原始函数前添加的新功能
        print("Before calling the original function")
        result = original_function(*args, **kwargs)
        # 这里是在调用原始函数后添加的新功能
        print("After calling the original function")
        return result

    return wrapper


@decorator_function
def target_function(arg1, arg2):
    print(f"Target function called with arguments: {arg1}, {arg2}")


target_function("sanduo", "water")

print("*" * 20)


# 带参数的装饰器
def decorator_function_with_arguments(decorator_arg):
    def decorator_function(original_function):
        def wrapper(*args, **kwargs):
            print(f"Decorator argument: {decorator_arg}")
            result = original_function(*args, **kwargs)
            return result

        return wrapper

    return decorator_function


@decorator_function_with_arguments("Hello, World!")
def target_function_with_arguments(arg1, arg2):
    print(f"Target function with arguments called with arguments: {arg1}, {arg2}")


target_function_with_arguments("zhangsan", "lisi")

print("*" * 20)


# 类装饰器
class DecoratorClass:
    def __init__(self, original_function):
        self.original_function = original_function

    def __call__(self, *args, **kwargs):
        print("Before calling the original function")
        result = self.original_function(*args, **kwargs)
        print("After calling the original function")
        return result


@DecoratorClass
def target_function_with_class_decorator(arg1, arg2):
    print(f"Target function with class decorator called with arguments: {arg1}, {arg2}")


target_function_with_class_decorator("王五", "马贝")
